################################################################################
#
#   The controller class, the class that runs them all. Loads and sets up ...
#   ... everything then runs the main event loop (RubyGame version).
#
################################################################################







################################################################################
#   The SHOOTINGGAMECONTROLLER class :
################################################################################
class ShootingGameController

  attr_accessor :screen, :width, :height,
                :player, :level, :projectiles



  ##############################################################################
  # CREATING a new instance of the class :
  ##############################################################################
  def initialize(w, h, files)

    ### The RubyGame part : ####################################################

    ### First, the SCREEN SETUP : ##############################################
    @width  = w
    @height = h

    @screen = Screen.new([@width, @height], 0, HWSURFACE)
    @screen.title = "RubyGameBulletML"
    @screen.show_cursor = false

    ### Second, the JOYSTICK SETUP : ###########################################
    if Joystick.num_joysticks > 0 then
      @joystick = Joystick.new(0)
      print "Could not connect to joystick 0.\n" if @joystick == SDLError
    else
      print "No joystick found.\nUse the keyboard.\n"
    end

    ### Third, the EVENT MANAGEMENT : ##########################################
    @events = EventQueue.new

    @clock = Clock.new
    @clock.target_framerate = 60

    @status = :running



    ### The LEVELML part : #####################################################

    # Creating a PLAYER instance : ---------------------------------------------
    @player                 = CustomPlayer.new(self,
                                               @width/2,
                                               4*@height/5,
                                               0.0,
                                               3)

    playerImage, playerRect = loadImage("Images/vaisseau.bmp", -1)
    @player.setImage(playerImage, playerRect)

    hitImage, hitRect       = loadImage("Images/touche.bmp", -1)
    @player.setHitImage(hitImage, hitRect)


    # Projectiles setup : ------------------------------------------------------
    projectileStyle                   = Hash.new
    projectileStyle['vx']             = 0
    projectileStyle['vy']             = -3
    projectileStyle['collisionType']  = :radius
    projectileStyle['collisionZone']  = 4
    projectileStyle['damage']         = 1
    # Custom part :
    projectileStyle['appearance']     = './Images/tir.bmp'

    @player.addProjectileType(projectileStyle)

    @projectiles            = []      # The projectiles the player shoots


    # The fixed math initialization : ------------------------------------------
    Trigo.initialize


    # The LEVELML part : -------------------------------------------------------
    @levelFiles             = files
    @levelCount             = files.length
    @currentLevelIndex      = 0

    @customClassesList                     = Hash.new
    @customClassesList['enemyAppearance']  = CustomEnemyAppearance
    @customClassesList['bulletAppearance'] = CustomBulletAppearance
    @customClassesList['onHit']            = CustomOnHit
    
    @level                  = CustomLevelML.new(self,
                                                @customClassesList,
                                                @levelFiles[@currentLevelIndex])



    ### FINAL SETUP : ##########################################################
    @screen.fill([0, 0, 0])
    @screen.update

  end



  ##############################################################################
  # Running the EVENT LOOP :
  ##############################################################################
  def run

    # Starting a loop that can only be exited when either the ESCAPE key ...   #
    # ... or a specific joystick button has been pressed :                     #
    ############################################################################
    loop do

      @clock.tick     # Waiting in order to garanty a fixed frame rate.


      # Parsing the EVENTS : ###################################################
      @events.each do |event|

        @player.eventResponse(event)    # Forwarding the event to the player ...
        # ... instance so it can update itself accordingly.

        # What is this event made of ? #########################################
        # ( the button assignments are for a PS2 Fighting Stick 2 ) ############
        case event
        when QuitEvent #--------------------------------------- QuitEvent : ----
          return

        when JoyDownEvent #------------------------------------ JoyDownEvent : -
          if event.button == 12 then return end     # Quit
            if event.button == 0 then return end     # Quit

        when KeyDownEvent #------------------------------------ KeyDownEvent : -

          # Leaving : ----------------------------------------------------------
          if    event.key == K_ESCAPE then return   # Quit

          # Pausing : ----------------------------------------------------------
          elsif event.key == K_P      then

            if @status == :running  then
              @status = :pause
            else
              @status = :running
            end

          end # End of pausing -------------------------------------------------

        end

      end # End of EVENT parsing ###############################################


      # RUNNING the game : #####################################################
      if @status == :running then

        # Running all the game's elements : ------------------------------------
        @player.run
        @level.run
        @projectiles.each do |p|
          p.run
        end

        # Drawing all the game's elements : ------------------------------------
        @screen.fill([0, 0, 0])

        @level.draw
        @player.draw
        @projectiles.each do |p|
          p.draw
        end

        # Updating the elements status : ---------------------------------------
        @level.updateStatus
        @player.updateStatus
        @projectiles.delete_if do |p|
          p.updateStatus == :dead
        end

        # Is the player dead ? -------------------------------------------------
        if @player.status == :dead then
          @player.lives  -= 1
          @player.x       = @width/2
          @player.y       = 4*@height/5
          @player.status  = :alive
        end

        # Is the level finished ? ----------------------------------------------
        # Has the player lost all his lives ? ----------------------------------
        if (@level.status == :finished) or (@player.lives == 0) then
          moveToNextLevel
        end

        @screen.update

      end

    end ### End of the main loop ###############################################

  end





  ##############################################################################
  # MOVING on to the next level :
  ##############################################################################
  def moveToNextLevel

    @projectiles.clear

    @player.x     = @width/2
    @player.y     = 4*@height/5
    @player.lives = 3

    #@currentLevelIndex+=1

    @level = CustomLevelML.new(self,
                               @customClassesList,
                               @levelFiles[@currentLevelIndex])

  end    

end ### End of the SHOOTINGGAMECONTROLLER class ################################
